/* initialize.c - initproc */

#include <i386.h>
#include <kernel.h>

extern	int	entry();        /* start of kernel image, use &start    */
extern	int	end();          /* end of kernel image, use &end        */
extern  long	freemem; 	/* start of free memory (set in i386.c) */
extern char	*maxaddr;	/* max memory address (set in i386.c)	*/

/************************************************************************/
/***				NOTE:				      ***/
/***								      ***/
/***   This is where the system begins after the C environment has    ***/
/***   been established.  Interrupts are initially DISABLED.  The     ***/
/***   interrupt table has been initialized with a default handler    ***/
/***								      ***/
/***								      ***/
/************************************************************************/

extern void root(void);
extern long initsp;

/*------------------------------------------------------------------------
 *  The init process, this is where it all begins...
 *------------------------------------------------------------------------
 */
initproc()				/* The beginning */
{
	kprintf( "\n\nCPSC 415, Jan 2012\n32 Bit Xeros 1.1\nLocated at: %x to %x\n", &entry, &end );

        /* Your code goes here */

	kprintf("Max addr is %d %x\n", maxaddr, maxaddr);
	kprintf("Kernel end: %d, stack: %d\n", &end, initsp);
	kprintf("create: %d, syscreate: %d\n", &create, &syscreate);

	kmeminit();
	contextinit();	
	pidcounterinit();
	proccontrolinit();
        
  	void (*rootproc)(void) = &root;	
	create(rootproc, STDSTACKSIZ);

	// create the idle process 
	void (*idleproc)(void) = &idle;
	idle_proc_ptr = get_pcb();
	__create(idleproc, STDSTACKSIZ, idle_proc_ptr, FALSE);

	dispatch();	
	/* This code should never be reached after you are done */
	for(;;) kprintf("In kernel, bad\n"); /* loop forever */
}

/*
*	The following is some of the testing code used for the kernel
*
*/

//	void* stack = kmalloc(4096);
//	void (*psptr)(void) = &printstuff;
//	int psptrasint = (int)psptr;

//	CPU_context* ctxt = (CPU_context*)((int)stack+4096-CPPADDING-sizeof(CPU_context));
//	ctxt->edi = 17;
//	ctxt->esi = 18;
//	ctxt->ebp = (int)ctxt;
//	ctxt->esp = (int)ctxt;
//	ctxt->ebx = 21;
//	ctxt->edx = 22;
//	ctxt->ecx = 23;
//	ctxt->eax = 24;
//	ctxt->iret_eip = psptrasint;
//	ctxt->iret_cs = getCS();
//	ctxt->eflags = 0;

//	PCB* testpcb = (PCB*)kmalloc(sizeof(PCB));
//	testpcb->pid = 33;
//	testpcb->state = PROC_READY;
//	testpcb->cpu_state = ctxt;
//	testpcb->stack = (void*)ctxt;
//
//	int kret = 0;
//
//	kprintf("Test PCB initialized\n");
//	kprintf("Switching context to test process\n");
//	kret = contextswitch(testpcb);
//	
//	kprintf("KERNEL:\n");
//	kprintf("\tcontextswitch returned: %d\n", kret);
//	kprintf("\tctsw_gvar (want 63333): %d\n", ctsw_gvar);
//	kprintf("\tputting 117 in ctsw_gvar and switching back to process\n\n");
//	ctsw_gvar = 117;
//	
//	kret = contextswitch(testpcb);			
//	if(kret==4)
//		kprintf("KERNEL:\n\tProcess \"Terminated\", SUCCESS!\n");			
//	else
//		kprintf("KERNEL:\n\tProcess did not return correctly, FAILURE!\n");

//void printstuff(void){
//	int pret = 0;
//	kprintf("PROCESS:\n");
//	kprintf("\tSeems to be working, setting eax to 3\n");
//	kprintf("\tand ecx to 63333 to simulate arguments passing\n\n");
//	__asm __volatile("movl $3, %%eax\n\t"
//			"movl $63333, %%ecx\n\t"
//			"int $63\n\t"
//			"movl %%eax, %[pret]"
//			:[pret] "=m" (pret)
//			:
//			:"%eax", "%ecx");
//				
//	kprintf("PROCESS:\n");
//	kprintf("\tKernel returned: %d from simulated arg passing\n\n", pret);
//	__asm __volatile("movl $4, %%eax\n\t"
//			"int $63"
//			:
//			:
//			:"%eax"); //return back to kernel
//}
